/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sistemasdistribuidos.enfileiramento;

import java.io.*;
import java.net.*;
import java.util.Arrays;

/**
 * O servidor possui 3 threads. Todos os pedidos são armazenados em uma fila. As
 * threads vão processando os pedidos que estão na fila e respondendo aos
 * clientes. As threads não são finalizadas, elas ficam processando quantos
 * pedidos chegarem na fila.
 *
 * @author Manoel Afonso Filho
 */
public class Servidor extends Thread {

    private ServerSocket socketServidor;

    public Servidor(ServerSocket socket) {
        this.socketServidor = socket;
    }

    @Override
    public void run() {
        //Permite que vários clientes se conectem a esta thread.
        while (true) {
            try {
                //Aguarda um cliente se conectar.
                System.out.println(this.getName() + " aguardando conexão.");
                Socket socketCliente = socketServidor.accept();

                //Obtém os fluxos de entrada e saída.
                ObjectOutputStream saida = new ObjectOutputStream(socketCliente.getOutputStream());
                saida.flush();
                ObjectInputStream entrada = new ObjectInputStream(socketCliente.getInputStream());

                //Lê o objeto enviado pelo cliente.
                Object obj = entrada.readObject();

                if (!(obj instanceof String)) {
                    //Ordena o vetor do cliente.
                    int[] arr = (int[]) obj;
                    Arrays.sort(arr);
                    //Simula um processamento demorado.
                    Thread.sleep(5000);
                    //Envia o vetor ordenado.
                    System.out.println(this.getName() + " enviando array ordenado.");
                    enviarMensagem(arr, saida);
                }

            } catch (IOException | ClassNotFoundException | InterruptedException ex) {
                System.err.println("Erro: " + ex);
            }
        }
    }

    /**
     * Envia um objeto para o cliente.
     *
     * @param msg Objeto a ser enviado.
     */
    private void enviarMensagem(Object msg, ObjectOutputStream saida) {
        try {
            saida.writeObject(msg);
            saida.flush();
        } catch (IOException ex) {
            System.err.println("Erro ao enviar \"" + msg + "\" : " + ex);
        }
    }

    /**
     * Cria o servidor com 3 threads.
     *
     * @param args
     * @throws IOException
     */
    public static void main(String args[]) throws IOException {
        System.out.println("Iniciando servidor com threads por enfileiramento.");
        
        ServerSocket socketServidor = new ServerSocket(2004);

        Servidor t1 = new Servidor(socketServidor);
        t1.setName("Thread 1");
        Servidor t2 = new Servidor(socketServidor);
        t2.setName("Thread 2");
        Servidor t3 = new Servidor(socketServidor);
        t3.setName("Thread 3");

        t1.start();
        t2.start();
        t3.start();
    }
}